package com.legendframework.core.dao.yaml;

import com.legendframework.core.dao.exception.DaoException;
import com.legendframework.core.dao.page.Page;
import com.legendframework.core.dao.page.PageUtil;
import com.legendframework.core.dao.support.ClassUtils;
import com.legendframework.core.dao.transaction.YamlTransaction;
import com.legendframework.core.dao.wrapper.Wrapper;
import com.legendframework.core.dao.yaml.enums.YamlStorageType;
import com.legendframework.core.dao.yaml.support.BaseMapYml;
import com.legendframework.core.dao.yaml.support.IBaseMapYml;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class DefaultOneToManyYamlDaoImpl<T> extends AbstractYamlDao<T> {

    /**
     * yaml底层实现
     */
    private IBaseMapYml<T> baseMapYml;

    /**
     * 用于反射创建对象是所需的空参构造
     */
    public DefaultOneToManyYamlDaoImpl() {
        super(null,null);
    }

    /**
     * 构造器
     * @param path 文件的绝对路径前缀
     * @param entityType 实体类类型
     */
    public DefaultOneToManyYamlDaoImpl(String path , Class<T> entityType, YamlTransaction yamlTransaction) {
        super(entityType,yamlTransaction);
        String yamlFileName = getYamlFileName(path, entityType);
        //是否需要初始化文件
        boolean flag = false;
        if (!new File(yamlFileName).exists()) {
            flag = true;
        }
        baseMapYml = new BaseMapYml<>(yamlFileName,entityType,yamlTransaction);
        getAll();
        if (flag) {
            saveDefaultEntity();
        }
    }

    @Override
    List<T> getAll() {
        if (getCacheAll().isEmpty()) {
            List<T> list = new ArrayList<>(baseMapYml.getAll().values());
            Map<Serializable, T> cache = list
                    .stream()
                    .collect(Collectors.toMap(ClassUtils::getIdByEntity, Function.identity(), (k, v) -> v));
            //存入缓存
            putCacheBatch(cache);
            return list;
        }
        return new ArrayList<>(getCacheAll());
    }

    @Override
    public int insert(T entity) {
        Serializable id = ClassUtils.getIdByEntity(entity);
        if (id == null) {
            throw new DaoException("执行insert时失败，ID为空,实体类: ["+entity.getClass()+"]");
        }
        T t = selectById(id);
        if (t != null) {
            return 0;
        }
        baseMapYml.save(String.valueOf(id),entity);
        //存入缓存
        putCacheOne(id,entity);
        return 1;
    }

    @Override
    public int deleteById(Serializable id) {
        T t = selectById(id);
        if (t == null) {
            return 0;
        }
        baseMapYml.delete(String.valueOf(id));
        //修改缓存
        deleteCacheByKey(id);
        return 1;
    }

    @Override
    public int delete(Wrapper<T> wrapper) {
        List<T> filter = filter(wrapper);
        int count = 0;
        for (T t : filter) {
            count += deleteById(String.valueOf(ClassUtils.getIdByEntity(t)));
        }
        return count;
    }

    @Override
    public int deleteBatchIds(Collection<? extends Serializable> idList) {
        int count = 0;
        for (Serializable id : idList) {
            count += deleteById(id);
        }
        return count;
    }

    @Override
    public int updateById(T entity) {
        Serializable id = ClassUtils.getIdByEntity(entity);
        if (id == null) {
            throw new DaoException("执行updateById时失败，ID为空,实体类: ["+entity.getClass()+"]");
        }
        T t = selectById(id);
        if (t == null) {
            return 0;
        }
        updateEntity(entity,t);
        baseMapYml.save(String.valueOf(id),t);
        //修改缓存
        putCacheOne(id,t);
        return 1;
    }

    @Override
    public int update(T entity, Wrapper<T> updateWrapper) {
        List<T> filter = filter(updateWrapper);
        int count = 0;
        for (T t : filter) {
            count += updateById(t);
        }
        return count;
    }

    @Override
    public T selectById(Serializable id) {
        T t = getCacheOne(id);
        if (t == null) {
            if (!baseMapYml.isExist()) {
                return null;
            }
            t = baseMapYml.get(String.valueOf(id));
            //存入缓存
            putCacheOne(id,t);
        }
        return t;
    }

    @Override
    public List<T> selectBatchIds(Collection<? extends Serializable> idList) {
        return getAll().stream().filter(item -> idList.contains(ClassUtils.getIdByEntity(item))).collect(Collectors.toList());
    }

    @Override
    public T selectOne(Wrapper<T> queryWrapper , boolean throwEx) {
        List<T> filter = filter(queryWrapper);
        if (filter.isEmpty()) {
            return null;
        }
        if (throwEx && filter.size() > 1) {
            throw new DaoException("查询不到不止一条记录");
        }
        return filter.get(0);
    }

    @Override
    public long selectCount(Wrapper<T> queryWrapper) {
        return filter(queryWrapper).size();
    }

    @Override
    public List<T> selectList(Wrapper<T> queryWrapper) {
        return filter(queryWrapper);
    }

    @Override
    public Page<T> selectPage(Page<T> page, Wrapper<T> queryWrapper) {
        List<T> filter = filter(queryWrapper);
        return PageUtil.page(filter,page.getCurrentPage(),page.getItemNum());
    }

    @Override
    public T getOne() {
        throw new DaoException("当前配置文件类型"+YamlStorageType.ONE_TO_MANY+",不支持getOne()");
    }
}
